﻿#region copyright
//<copyright>
// Copyright(C) 2012 TrackerRealm Corporation
// This file is part of the open source project - Jazz. http://jazz.codeplex.com
// 
// Jazz is open software: you can redistribute it and/or modify it 
// under the terms of the GNU Affero General Public License (AGPL) as published by 
// the Free Software Foundation, version 3 of the License.
// 
// Jazz is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty 
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
//  See the GNU Affero General Public License (AGPL) for more details.
// 
// You should have received a copy of the GNU General Public 
// License along with Jazz.  If not, see <http://www.gnu.org/licenses/>.
//
// REMOVAL OF THIS NOTICE IS VIOLATION OF THE COPYRIGHT. 
//</copyright>
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Serialization;
using TrackerRealm.Jazz.Common;
using TrackerRealm.Jazz.Client;

namespace TrackerRealm.Jazz.Client.Services
{
    #region SerializerCache
    /// <summary>
    /// Provides a cache for Jazz objects during deserialization.
    /// <para>All requests for Jazz objects will be honored since the
    /// cache will create a blank jazz object if it does not exist.</para>
    /// <para>This class is useful for deserializing jazz objects with forward, or circular,
    /// references.</para>
    /// </summary>
    public class SerializerService
    {
        Dictionary<Guid, jObject> dict;
        List<Guid> initializedObjList = new List<Guid>();
        /// <summary>
        /// constructor
        /// </summary>
        public SerializerService()
        {
            this.dict = new Dictionary<Guid, jObject>();
        }
        /// <summary>
        /// Returns a Jazz object of the specified type and ID.
        /// If the object does not exist one will be created.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="jazzType">To create a Jazz type the method 
        /// '<see cref="JazzServices.GetTypeFromName(string)"/>' can be used.</param>
        /// <returns></returns>
        public jObject Create(Guid id, Type jazzType)
        {
            jObject jazzObj;
            if (!this.dict.TryGetValue(id, out jazzObj))
            {
                // create a jazz object
                jazzObj = (jObject)FormatterServices.GetUninitializedObject(jazzType);
                jObjectFields.Id.SetValue(jazzObj, id);
                this.dict.Add(id, jazzObj);
                // The 'Link' bit will be overridden if this 'jazzObj' is restored.
                jObjectFields.Flags.SetValue(jazzObj, JazzFlagsType.Link);
            }
            return jazzObj;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        public void SetInitializedFlag(Guid id)
        {
            this.initializedObjList.Add(id);
        }
        /// <summary>
        /// Returns an array of Guids that represent Jazz
        /// objects that were created, but never initialized.
        /// </summary>
        /// <returns></returns>
        public Guid[] UnInitialized()
        {
            return this.dict.Keys.Except(this.initializedObjList).ToArray();
        }
        /// <summary>
        /// Clear the internal cache.
        /// </summary>
        public void Clear()
        {
            this.dict.Clear();
            this.initializedObjList.Clear();
        }
    }
    #endregion
}
